/*
    YmsgIRC - Program enabling YMSG chat clients to use IRC
    Copyright (C) 2011 Crash Daemonicus ( crashenator -at- gmail.com )

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "common.h"



#ifdef COMMON_DBG
    int giCommon_DbgLvl=0;
    bool gcCommon_DbgNL=true;
    
    void dbg_linestart(){if(!gcCommon_DbgNL){ dbgtext("\n");}}
    void dbg_indent(){for(int i=0;i<giCommon_DbgLvl;i++) dbgtext("   ");}
    void dbg_line(const char* file,int line,bool indent)
    {
        dbg_linestart();
        if(line!=-1) printf("@%04d %-6.6s| ",line,file);
        else printf("@---- %-6.6s| ",line,file);
        if(indent) dbg_indent();
    }
    void dbghead(const char* c, const char* file, int line)
    {
        dbg_line(file,line,true);
        
        if(c!=NULL){dbgtext(c);}
        //if(file!=0){dbgtext(" - ");dbgtext(file);}
        dbgtext("{\n",true,file,line);
        giCommon_DbgLvl++;
    }
    void dbgfoot(const char* c,const char* file,int line){
        giCommon_DbgLvl--; 
        dbg_line(file,line,true);
        dbgtext("} ");
        if(c!=NULL) dbgtext(c);; 
        dbg("\n");
    }
    void dbgtext(const char* c,bool indent,const char* file, int line){
        //this is just here so it can be commented out with a release
        if(indent) {
            dbg_line(file,line,true);
        }
        if(c==NULL){cputs("\n< dbg(NULL) >\n");gcCommon_DbgNL=true;}
        else {
            cputs(c);
            gcCommon_DbgNL = ( c[strlen(c)-1] == '\n' );
        }
        return;
    }
    void dbgtext(const string& s,bool indent,const char* file,int line){
        dbgtext(s.c_str(),indent,file,line);
        return;
    }
/*#else
    void dbg_indent() {;}
    void dbghead(const char* c){;}
    void dbgfoot(const char* c){;}
    void dbgtext(const char* c,bool indent){;}*/
#endif

string itos(int i)
{
    char cs[16];
    itoa(i,cs,10);
    return string(cs);
}
int iLimit(int val, int min, int max)
{
    if(val<min) return min;
    if(val>max) return max;
    return val;
}
bool iCheckLimit(int val, int min, int max)
{
    if(val<min) return false;
    if(val>max) return false;
    return true;
}


void StringTokenize(const string& str,
                      vector<string>& tokens,
                      const string& delimiters)
{
    // Skip delimiters at beginning.
    string::size_type lastPos = str.find_first_not_of(delimiters, 0);// Find first "non-delimiter".
    string::size_type pos     = str.find_first_of(delimiters, lastPos);// find the first in-content delimiter

    while (string::npos != pos || string::npos != lastPos)
    {
        // Found a token, add it to the vector.
        tokens.push_back(str.substr(lastPos, pos - lastPos));
        // Skip delimiters.  Note the "not_of"
        lastPos = str.find_first_not_of(delimiters, pos);// Find next "non-delimiter"
        pos = str.find_first_of(delimiters, lastPos);//find the next delimeter
    }
}
void StringExplode(const string& str, vector<string>& parts, const string& delimiter)//NOTE: this will not ignore beginning delims and WILL ignore text after the last delim
{
	string::size_type posFrom   =0;
	string::size_type posCurrent=0;
	string::size_type dellen=delimiter.length();
	while(posCurrent!=string::npos){
		posCurrent=str.find(delimiter,posFrom);
		if(posCurrent!=string::npos){ 
			parts.push_back(  str.substr(posFrom, posCurrent - posFrom)  );
			posFrom=posCurrent + dellen;
		}
	}
}

string stringtok(const string& str,const string& delimiters)
{
	vector<string> tokens;
	StringTokenize(str,tokens,delimiters);
	if(tokens.size()<1) return str;
	return tokens.front();
}

bool stringreplace(string& s, const string& sub, const string& sub2)
{
    bool rep=false;
    size_t l=sub.length();//strlen(sub);
    size_t p=s.find(sub);
    while(p!=-1)
    {
        rep=true;
        s.replace(p,l,sub2);
        p=s.find(sub);
    }
    return rep;
}


void puts(const string& s){puts(s.c_str());}
void cputs(const string& s){cputs(s.c_str());}
void cputs(const char* c){fputs(c,stdout);}


void MemReverse(void* p,int l)
{
    char* s=(char*)p;
    //char* e=(char*)(  ((int)p) + (l-1)  );//ugly, but otherwise I get errors.
	char* e=(char*)(  ((char*)p) + (l-1)  );//ugly, but otherwise I get errors.
    unsigned char ts;
    while(s<e)
    {
        ts=*s;
        *s=*e;
        *e=ts;
        
        s++;
        e--;
    }
}
//void MemZero(void* p,int l){memset(p, 0, l);}




char* newstr(const char* c,bool safe,size_t alloc)
{
    dbg_head("newstr(const char* c,bool safe,int alloc)");
    if(c==NULL)
    {
        dbgline("nullin");
        if(safe){
           char* cn=new char[alloc+1];
           MEMZERO(cn,alloc+1);
           ReturnX(cn,"safe");
        }else{ReturnD(NULL);}
    }
    dbgline("'");dbg(c);dbg("'");
    
    if(alloc==0) alloc=strlen(c);
    char* cn=new char[alloc+1];
    cn[alloc]=0;//necessary if alloc<strlen
    
    dbgline("strncpy");
    strncpy(cn,c,alloc);
    ReturnD(cn);
}


bool delstr(const char** pc)
{
    dbg_head("delstr(const char** pc)");
    using namespace std;
    if(pc!=NULL){
        if(*pc!=NULL){
            dbgline("'");dbg(*pc);dbg("'");
            delete[] (*pc);
            *pc=NULL;
            dbg_foot(0);
            return true;
        }
    }
    dbg_foot("null");
    return false;
}
bool delstr(char** pc)
{
    dbg_head("delstr(char** pc)");
    using namespace std;
    if(pc!=NULL){
        if(*pc!=NULL){
            delete[] (*pc);
            *pc=NULL;
            dbg_foot(0);
            return true;
        }
    }
    dbg_foot("null");
    return false;
}


